#!/usr/bin/env ruby
#Universidad del Valle de Guatemala
#Sistemas Operativos Avanzados
#David Ytzen Hsieh Lo #08225

require 'socket'
require 'thread'
require 'monitor'
require 'rexml/document'
require 'logger'

include REXML

#Load config xml file
file = File.new("config.xml")
doc = Document.new(file)

#Parse config xml tree
root = doc.root
$baseDirPath = root.elements["baseDir"].text  
$baseDirPath.gsub!(/[\n]+/, "");

#Add / if missing
if ($baseDirPath[$baseDirPath.length-1] != 47)
  $baseDirPath += "/"
end
#REMOVE
puts $baseDirPath

#Create log
$log = Logger.new("./server.log")
$log.level = Logger::DEBUG
$log.info "-------------------------------"

class Worker < Thread

  def initialize(buffer)
    super(buffer) { |buffer|
      begin
        loop do
          socket = buffer.get
          
          request = socket.readline         
          puts request

          #Log request
          request.gsub!(/[\n]+/, "");
          $log.info request

          validGET = request.match(/GET .* HTTP\/1\.1/)
          puts validGET
          
          #Log host
          host = socket.readline
          host.gsub!(/[\n]+/, "");
          $log.info host

          puts socket.readline
          puts socket.readline#User-agent
          puts socket.readline#Accept filetype
          puts socket.readline#Accept lang
          puts socket.readline#encoding
          puts socket.readline#charset
          puts socket.readline#keepalive
          puts socket.readline#connection (keepalive)
          puts socket.readline#cachecontrol

          unless (validGET)
            puts "Bad request"
            socket.puts "HTTP/1.1 400 Bad Request\n"
            $log.info "HTTP/1.1 400 Bad Request"
            socket.close
            next
          end
          
          file = request.split(' ')[1]
          file = '.' + file
          
          unless ( File.exists?(file) )
            puts "Not found"
            $log.info "HTTP/1.1 404 File Not Found"
            $log.info "Requested file: " + file
            socket.puts "HTTP/1.1 404 File Not Found\n"
            socket.puts "\n"
            socket.puts"File not found"
            #socket.puts "<html>maldiciion</html>"
            socket.close
            next
          end
		
		
		
          $log.info "HTTP/1.1 200 OK"
          socket.puts "HTTP/1.1 200 OK\n"
          socket.puts "Connection: close\n"
          socket.puts "Content-Type: text/html\n"
          if(file == "./")
            file = "index.html"			
          end
          
          $log.info "Requested file: " + file

          file = $baseDirPath + file;
          
          File.open(file, 'r') { |f|
            
            while (line = f.gets)
              socket.puts line
            end
            
          }
          
          socket.close
        end
      rescue Exception => e
        $stderr.puts $!.inspect
      end
    }
  end
end


class SynchronisedBuffer < Monitor

   def initialize(capacity)
     @capacity = capacity
     @front = 0
     @back = 0
     @elements = Array.new(capacity)
     @empty_cond = new_cond
     @full_cond = new_cond
     super()
   end
   
   def get
     synchronize do
       @empty_cond.wait_while {empty?}
       element = @elements[@front]
       @elements[@front] = nil
       @front = (@front + 1) % @capacity
       @full_cond.signal
       return element
     end
   end
   
   def put(element)
     synchronize do
       @full_cond.wait_while {full?}
       @elements[@back] = element
       @back = (@back + 1) % @capacity
       @empty_cond.signal
     end
   end
   
   def full?
     synchronize do
       (@front == @back and @elements[@front] != nil)
     end
   end
   
   def empty?
     synchronize do
       (@front == @back and @elements[@front] == nil)
     end
   end
   
 end
 
 
 server = TCPServer.new('127.0.0.1', '81')
 
 buffer = SynchronisedBuffer.new(100)

 workers = []
 
 for i in (1..40)
   workers[i] = Worker.new(buffer)
   workers[i][:name] = 'worker' + i.to_s
 end
 
 while socket = server.accept
   buffer.put(socket)
 end
 
